from Resources.Enums import *


class Token:
    def __init__(self, tagval=None, kindval=None):
        self.tag = tagval
        self.kind = kindval


class Clause:
    def __init__(self):
        self.tokens = [Token()] * 50
        self.len = 0
        self.grammerVal = 0
        self.kindVal = 0
        self.clauseType = None

    def get(self, idx):
        return self.tokens[idx]

    def insert(self, idx, token):
        self.tokens.insert(idx, token)
        self.len += 1

    def append(self, token):
        self.tokens[self.len] = token
        self.len = self.len + 1
        if token.kind == Kind.GRAMMER:
            self.grammerVal = self.grammerVal | (1 << token.tag.value)
        else:
            self.kindVal = self.kindVal | (1 << (token.kind.value - 2))

    def sortTokens(self):
        self.tokens = sorted(
            self.tokens[:self.len], key=lambda token: token.kind.value)
        for i in range(self.len):
            if i >= self.len:
                break
            if i > 0 and self.tokens[i].kind != Kind.GRAMMER and self.tokens[i].kind != Kind.OBJECT and self.tokens[i].kind == self.tokens[i - 1].kind:
                self.tokens.pop(i)
                self.len -= 1


class Sentence:
    # 记录语法词数量，和语法词、标点以外关键词种类数量的常量
    grammerNum = 4
    kindNum = 5

    def __init__(self):
        self.clauses = [Clause()] * 10
        self.len = 0

    def get(self, idx):
        return self.clauses[idx]

    def append(self, clause):
        self.clauses[self.len] = clause
        self.len = self.len + 1

    def pop(self, loc):
        self.clauses.pop(loc)
        self.len -= 1

    def insert(self, idx, clause):
        self.clauses.insert(idx, clause)
        self.len += 1

    def decode(self, num, maxSize):
        ret = [0] * maxSize
        for i in range(maxSize):
            if num & (1 << i):
                ret[i] = 1
        return ret

    def predictClauseType(self):
        # loc = 0
        # for clause in self.clauses:
        #     featureList = self.decode(
        #         clause.grammerVal, self.grammerNum) + self.decode(clause.kindVal, self.kindNum) + [loc, self.clauses - loc]
        #     loc += 1
        # # read model parameters, predict

        for i in range(self.len):
            clause = self.clauses[i]
            if clause.grammerVal & (1 << Tag.IF.value):
                clause.clauseType = ClauseType.IF_CLAUSE
                continue
            elif clause.grammerVal & (1 << Tag.THEN.value):
                clause.clauseType = ClauseType.THEN_CLAUSE
                continue
            elif clause.grammerVal & (1 << Tag.AND.value):
                clause.clauseType = ClauseType.AND_CLAUSE
                continue
            elif clause.grammerVal & (1 << Tag.OR.value):
                clause.clauseType = ClauseType.OR_CLAUSE
                continue
            else:
                cnt = 0
                if clause.kindVal & (1 << Kind.ATTRIBUTE.value - 2):
                    cnt += 1
                if clause.kindVal & (1 << Kind.RELATION.value - 2):
                    cnt += 1
                if clause.kindVal & (1 << Kind.NUM.value - 2):
                    cnt += 1
                if clause.kindVal & (1 << Kind.SPECIAL.value - 2):
                    if cnt >= 2:
                        clause.clauseType = ClauseType.IF_CLAUSE
                    else:
                        clause.clauseType = ClauseType.THEN_CLAUSE
                elif cnt >= 1:
                    clause.clauseType = ClauseType.IF_CLAUSE
                else:
                    clause.clauseType = ClauseType.THEN_CLAUSE

    def sortClause(self):
        # sort clause order, make IF_CLAUSE and their AND/OR_CLAUSE in front
        loc = self.len - 1
        for i in range(self.len):
            if self.clauses[i].clauseType == ClauseType.THEN_CLAUSE:
                loc = i - 1
                break
        i = loc + 1
        while i < self.len:
            if self.clauses[i].clauseType == ClauseType.IF_CLAUSE:
                if i != loc + 1:
                    self.clauses.insert(loc + 1, self.clauses[i])
                    self.clauses.pop(i + 1)
                loc += 1
            i += 1

    def sort(self):
        self.sortClause()
        for clause in self.clauses:
            clause.sortTokens()
